package freemarker;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import lang.MultiFile;
import log.Log;
import log.Logger;
import util.StringHelper;
import freemarker.ext.beans.StringModel;
import freemarker.template.SimpleSequence;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelIterator;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;

public abstract class BaseTag implements TemplateDirectiveModel {
	
	/**
	 * 日志操作类，子类可以使用
	 */
	protected Logger logger = Log.get(this.getClass());
	
    /**
     * <方法描述> 获取参数字符串值，若不存在，则返回null
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected String getStringValue(String fieldName, Map params) throws TemplateModelException {
        String value = null;
        TemplateModel paramValue = (TemplateModel) params.get(fieldName);
        if (paramValue != null) {
            value = parseString(paramValue);
        }
        return value;
    }

    /**
     * <方法描述> 将获取到的TemplateMode对象，转化为字符串，不过有些尚不知如何转化，则直接抛出异常。以后扩展此方法即可
     * 
     * @param templateModel
     * @return
     * @throws TemplateModelException
     */
    private String parseString(TemplateModel templateModel) throws TemplateModelException {
        String value = "";
        if (templateModel instanceof StringModel) {
            Object param = ((StringModel) templateModel).getWrappedObject();
            if (param.getClass().isEnum()) {
                value = ((Enum) param).name();
            } else if (param.getClass().equals(MultiFile.class)) {
                value = ((MultiFile) param).getValue();
            } else {
                value = param.toString();
            }
        } else if (templateModel instanceof TemplateScalarModel) {
            value = ((TemplateScalarModel) templateModel).getAsString();
        } else if (templateModel instanceof TemplateSequenceModel) {
            Iterator it = ((SimpleSequence) templateModel).toList().iterator();
            StringBuilder sb = new StringBuilder();
            while (it.hasNext()) {
                if (sb.length() > 0) {
                    sb.append(",");
                }
                Object item = it.next();
                if (item != null) {
                    if (item.getClass().isEnum()) {
                        sb.append(((Enum) item).name());
                    } else {
                        sb.append(item);
                    }
                }
            }
            value = sb.toString();
        } else if (templateModel instanceof TemplateCollectionModel) {
            TemplateModelIterator it = ((TemplateCollectionModel) templateModel).iterator();
            StringBuilder sb = new StringBuilder();
            while (it.hasNext()) {
                TemplateModel model = it.next();
                if (sb.length() > 0) {
                    sb.append(",");
                }
                sb.append(parseString(model));
            }
            value = sb.toString();
        } else if (templateModel instanceof TemplateNumberModel) {
            value = ((TemplateNumberModel) templateModel).getAsNumber().toString();
        } else if (templateModel instanceof TemplateBooleanModel) {
            value = String.valueOf(((TemplateBooleanModel) templateModel).getAsBoolean());
        } else if (templateModel instanceof TemplateDateModel) {
            value = ((TemplateDateModel) templateModel).getAsDate().toString();
        } else {
            throw new TemplateModelException("The \"" + templateModel + "\" parameter " + "cannot parse String.");
        }
        return value;
    }

    /**
     * <方法描述>获取参数字符串值，若不存在或空串，则抛出异常
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected String getRequireStringValue(String fieldName, Map params) throws TemplateModelException {
        String value = getStringValue(fieldName, params);
        if (!StringHelper.hasLength(value)) {
            throw new TemplateModelException("The required \"" + fieldName + "\" paramter" + "is missing.");
        } else {
            return value;
        }
    }

    /**
     * <方法描述>获取参数字符串值，若不存在，则返回默认值
     * 
     * @param fieldName
     * @param params
     * @param defaultValue
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected String getStringValueWithDefault(String fieldName, Map params, String defaultValue)
                                                                                                 throws TemplateModelException {
        String value = getStringValue(fieldName, params);
        if (value == null) {
            return defaultValue;
        } else {
            return value;
        }
    }

    /**
     * <方法描述>获取参数Boolean值，若不存在，则返回false
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected boolean getBooleanValue(String fieldName, Map params) throws TemplateModelException {
        Boolean value = getBooleanValueWithNull(fieldName, params);
        return (value == null ? false : value);
    }

    /**
     * <方法描述>获取参数Boolean值，若不存在，则返回null
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Boolean getBooleanValueWithNull(String fieldName, Map params) throws TemplateModelException {
        Boolean value = null;
        TemplateModel paramValue = (TemplateModel) params.get(fieldName);
        if (paramValue != null) {
            if (!(paramValue instanceof TemplateBooleanModel)) {
                throw new TemplateModelException("The \"" + fieldName + "\" parameter " + "must be a Boolean.");
            } else {
                value = ((TemplateBooleanModel) paramValue).getAsBoolean();
            }
        }
        return value;
    }

    /**
     * <方法描述>获取参数Boolean值，若不存在，则抛出异常
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Boolean getRequireBooleanValue(String fieldName, Map params) throws TemplateModelException {
        Boolean value = getBooleanValueWithNull(fieldName, params);
        if (value == null) {
            throw new TemplateModelException("The required \"" + fieldName + "\" paramter" + "is missing.");
        } else {
            return value;
        }
    }

    /**
     * <方法描述>获取参数Boolean值，若不存在，则返回默认值
     * 
     * @param fieldName
     * @param params
     * @param defaultValue
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Boolean getBooleanValueWithDefault(String fieldName, Map params, boolean defaultValue)
                                                                                                    throws TemplateModelException {
        Boolean value = getBooleanValueWithNull(fieldName, params);
        if (value == null) {
            return defaultValue;
        } else {
            return value;
        }
    }

    /**
     * <方法描述>获取参数Number值，若不存在，则返回Null
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Number getNumberValue(String fieldName, Map params) throws TemplateModelException {
        Number value = null;
        TemplateModel paramValue = (TemplateModel) params.get(fieldName);
        if (paramValue != null) {
            if (!(paramValue instanceof TemplateNumberModel)) {
                throw new TemplateModelException("The \"" + fieldName + "\" parameter " + "must be a Number.");
            } else {
                value = ((TemplateNumberModel) paramValue).getAsNumber();
            }
        }
        return value;
    }

    /**
     * <方法描述>获取参数Number值，若不存在，则抛出异常
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Number getRequireNumberValue(String fieldName, Map params) throws TemplateModelException {
        Number value = getNumberValue(fieldName, params);
        if (value == null) {
            throw new TemplateModelException("The required \"" + fieldName + "\" paramter" + "is missing.");
        } else {
            return value;
        }
    }

    /**
     * <方法描述>获取参数Number值，若不存在，则返回默认值
     * 
     * @param fieldName
     * @param params
     * @param defaultValue
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Number getNumberValueWithDefault(String fieldName, Map params, Number defaultValue)
                                                                                                 throws TemplateModelException {
        Number value = getNumberValue(fieldName, params);
        if (value == null) {
            return defaultValue;
        } else {
            return value;
        }
    }

    /**
     * <方法描述>获取参数Date值，若不存在，则返回Null
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Date getDateValue(String fieldName, Map params) throws TemplateModelException {
        Date value = null;
        TemplateModel paramValue = (TemplateModel) params.get(fieldName);
        if (paramValue != null) {
            if (!(paramValue instanceof TemplateDateModel)) {
                throw new TemplateModelException("The \"" + fieldName + "\" parameter " + "must be a Date.");
            } else {
                value = ((TemplateDateModel) paramValue).getAsDate();
            }
        }
        return value;
    }

    /**
     * <方法描述>获取参数Date值，若不存在，则抛出异常
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Date getRequireDateValue(String fieldName, Map params) throws TemplateModelException {
        Date value = getDateValue(fieldName, params);
        if (value == null) {
            throw new TemplateModelException("The required \"" + fieldName + "\" paramter" + "is missing.");
        } else {
            return value;
        }
    }

    /**
     * <方法描述>获取参数Date值，若不存在，则返回默认值
     * 
     * @param fieldName
     * @param params
     * @param defaultValue
     * @return
     * @throws TemplateModelException
     * @example <调用范例>
     */
    protected Date getDateValueWithDefault(String fieldName, Map params, Date defaultValue)
                                                                                           throws TemplateModelException {
        Date value = getDateValue(fieldName, params);
        if (value == null) {
            return defaultValue;
        } else {
            return value;
        }
    }

    /**
     * <方法描述> 获取List对象
     * 
     * @param fieldName
     * @param params
     * @return
     * @throws TemplateModelException
     */
    protected List getListDataValue(String fieldName, Map params) throws TemplateModelException {
        List value = null;
        TemplateModel paramValue = (TemplateModel) params.get(fieldName);
        if (paramValue != null) {
            if (!(paramValue instanceof TemplateSequenceModel)) {
                throw new TemplateModelException("The \"" + fieldName + "\" parameter " + "must be a sequence data.");
            } else {
                value = ((SimpleSequence) paramValue).toList();
            }
        }
        return value;
    }
}
